package com.cn.http.enums;

import com.cn.http.http.impl.FileUpload;
import com.cn.http.utils.MapUtils;
import com.cn.http.utils.StrUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Random;

/**
 * &#064;Time 2024 八月 星期六 23:58
 *
 * @author ShangGuan
 */
public enum TypeBodyEnum implements TypeBody {

    /**
     * application/json
     */
    TYPE_APPLICATION_JSON {
        @Override
        public String to(Map<String, Object> param) {
            return MapUtils.mapStrToJson(param);
        }

        @Override
        public String getHeader() {
            return "application/json";
        }

        @Override
        public void write(OutputStream out, String body, FileUpload fileUpload) throws IOException {
            out.write(body.getBytes(StandardCharsets.UTF_8));
        }


    },
    /**
     * multipart/from-data
     */
    TYPE_MULTIPART_FORM_DATA {
        private volatile String boundary;
        @Override
        public String getBoundary() {
            synchronized (this){
                if (StrUtils.isEmpty(boundary)) {
                    this.boundary = "-------------------------" + generateBoundary();
                    return boundary;
                }
            }
            return boundary;
        }

        @Override
        public String to(Map<String, Object> param) {

            return MapUtils.mapToFromData(param, getBoundary());
        }

        @Override
        public String getHeader() {
            return "multipart/form-data; boundary=" + getBoundary();
        }

        @Override
        public void write(OutputStream out, String body, FileUpload fileUpload) throws IOException {
            try (InputStream inputStream = fileUpload.getInputStream()) {
                if (!StrUtils.isEmpty(body)) {
                    out.write(body.getBytes());
                }
                int bytesRead;
                out.write(("--"+getBoundary()+"\r\n").getBytes());
                //Content-Disposition: form-data; name="file"; filename="my-setting.txt"
                String contentDisposition = "Content-Disposition: form-data; name=\"" + fileUpload.getName() + "\"; " +
                        "filename=\"" + fileUpload.getFileName() + "." + fileUpload.getSuffix() + "\"" +
                        "\r\n";
                out.write(contentDisposition.getBytes());
                String contentType = FileEnum.getInstance(fileUpload.getSuffix()).getFileContentType() + "\r\n";
                out.write(contentType.getBytes());
                out.write("\r\n".getBytes());
                while ((bytesRead = inputStream.read()) != -1) {
                    out.write(bytesRead);
                }
                out.write("\r\n".getBytes());
                out.write(("--"+getBoundary()+"--").getBytes());
            }
        }
    },

    /**
     * application/w-www-from-url-encoded
     */
    TYPE_X_WWW_FROM_URL_ENCODED {
        @Override
        public String to(Map<String, Object> param) {
            return MapUtils.mapToFormUrlEncoded(param);
        }

        @Override
        public String getHeader() {
            return "application/x-www-form-urlencoded";
        }

        @Override
        public void write(OutputStream out, String body, FileUpload fileUpload) throws IOException {
            out.write(body.getBytes(StandardCharsets.UTF_8));
        }
    },

    /**
     * text/plan
     */
    TYPE_TEXT_PLAN {
        @Override
        public String to(Map<String, Object> param) {
            throw new RuntimeException("text/plain 请自己实现");
        }

        @Override
        public String getHeader() {
            return "text/plain";
        }

        @Override
        public void write(OutputStream out, String body, FileUpload fileUpload) throws IOException {
            out.write(body.getBytes(StandardCharsets.UTF_8));
        }
    },
    ;

    public String getBoundary() {
        try {
            throw new NoSuchMethodException("No Method");
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    public static String generateBoundary() {
        Random random = new Random();
        StringBuilder boundary = new StringBuilder();
        for (int i = 0; i < 24; i++) {
            boundary.append(random.nextInt(10));
        }
        return boundary.toString();
    }
}
